jetcrab\bytecode\statements/
control_statements.rs1use crate::ast::Node;
2use crate::vm::instructions::Instruction;
3use crate::vm::types::CodeAddress;
4
5use super::{ControlFlowCore, LabelManager};
6
7pub fn generate_break_statement<T>(this: &mut T, node: &Node)
8where
9 T: ControlFlowCore + LabelManager,
10{
11 if let Node::BreakStatement(stmt) = node {
12 if let Some(label) = &stmt.label {
13 if let Node::Identifier(label_name) = &**label {
15 if let Some(label_end_address) = this.get_label_end_address(label_name) {
16 this.instructions()
18 .push(Instruction::Jump(label_end_address));
19 } else {
20 this.instructions()
22 .push(Instruction::Jump(CodeAddress::new(9999)));
23 }
24 } else {
25 this.instructions()
27 .push(Instruction::Jump(CodeAddress::new(9999)));
28 }
29 } else {
30 this.instructions()
32 .push(Instruction::Jump(CodeAddress::new(9999)));
33 }
34 }
35}
36
37pub fn generate_continue_statement<T>(this: &mut T, node: &Node)
38where
39 T: ControlFlowCore + LabelManager,
40{
41 if let Node::ContinueStatement(stmt) = node {
42 if let Some(label) = &stmt.label {
43 if let Node::Identifier(label_name) = &**label {
45 if let Some(label_start_address) = this.get_label_start_address(label_name) {
46 this.instructions()
48 .push(Instruction::Jump(label_start_address));
49 } else {
50 this.instructions()
52 .push(Instruction::Jump(CodeAddress::new(8888)));
53 }
54 } else {
55 this.instructions()
57 .push(Instruction::Jump(CodeAddress::new(8888)));
58 }
59 } else {
60 this.instructions()
62 .push(Instruction::Jump(CodeAddress::new(8888)));
63 }
64 }
65}
66
67pub fn generate_return_statement<T>(this: &mut T, node: &Node)
68where
69 T: ControlFlowCore,
70{
71 if let Node::ReturnStatement(stmt) = node {
72 if let Some(arg) = &stmt.argument {
73 this.visit_node(arg);
74 }
75 this.instructions().push(Instruction::Return);
76 }
77}
78
79pub fn generate_labeled_statement<T>(this: &mut T, node: &Node)
80where
81 T: ControlFlowCore + LabelManager,
82{
83 if let Node::LabeledStatement(stmt) = node {
84 let label_name = if let Node::Identifier(name) = &*stmt.label {
86 name.clone()
87 } else {
88 "unknown".to_string()
89 };
90
91 let label_start = this.instructions().len();
93
94 this.add_label(
96 format!("{}_start", label_name),
97 CodeAddress::new(label_start),
98 );
99
100 this.push_current_label(label_name.clone());
102
103 this.visit_node(&stmt.body);
105
106 let label_end = this.instructions().len();
108
109 this.add_label(format!("{}_end", label_name), CodeAddress::new(label_end));
111
112 this.pop_current_label();
114
115 }
118}